package net.oov.identify;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import net.oov.identify.StatusTree.TreeNode;
import net.oov.identify.util.CharExtUtil;

/**
 * container for frequency of char sequence
 * 串频容器（具备字典的查询和添加功能）
 * 
 * @author huangsui.cn
 *
 */
public class SequenceFreqContainer{

	public static final int LOAD_METHOD_FORWARD = 0;//load forward dic only
	public static final int LOAD_METHOD_REVERSE = 1;//load reverse dic only
	public static final int LOAD_METHOD_BOTH = 2;//load both forward and reverse dic 
	
	private int loadMethod = -1;
	private int maxSeqLengthAllowed = -1;
	private Map<Character, StatusTree> seqFreqDic = new HashMap<Character, StatusTree>();
	private Map<Character, StatusTree> seqFreqRevDic = new HashMap<Character, StatusTree>();
	
	public SequenceFreqContainer(int loadMethod, int maxSeqLengthAllowed){
		super();
		this.loadMethod = loadMethod;
		this.maxSeqLengthAllowed = maxSeqLengthAllowed;
	}
	
	/**
	 * 
	 * @param charSequence
	 */
	public TreeNode addCharSequence(char[] cs){
		return this.addCharSequence(cs, Boolean.FALSE);
	}

	/**
	 * add all char in CharSequence to the container
	 * @param charSequence
	 * @param isWhole 
	 * 		is not segmenting by program
	 * @return
	 */
	public TreeNode addCharSequence(char[] cs, Boolean isWhole){
		
		StatusTree st = null;
		TreeNode ret = null;

		if(loadMethod == LOAD_METHOD_FORWARD){
			st = this.getRootNode(seqFreqDic, cs);
			ret = st.addNodes(cs, isWhole);
		}else if(loadMethod == LOAD_METHOD_REVERSE){
			st = this.getRootNode(seqFreqRevDic, cs);
			ret = st.addNodes(cs, isWhole);
		}else if(loadMethod == LOAD_METHOD_BOTH){
			//正向
			st = this.getRootNode(seqFreqDic, cs);
			st.addNodes(cs, isWhole);
			//逆向
			cs = CharExtUtil.reverse(cs);
			st = this.getRootNode(seqFreqRevDic, cs);
			st.addNodes(cs, isWhole);
		}else{
			throw new RuntimeException("参数异常：请初始化参数loadMethod");
		}
		
		return ret;
		
	}
	
	/**
	 * @param cs
	 * @return
	 */
	private StatusTree getRootNode(Map<Character, StatusTree> dic, char[] cs){
		StatusTree st = dic.get(cs[0]);
		if(st == null) {
			st = new StatusTree();
			dic.put(cs[0], st);
		}
		return st;
	}
	
	public Map<Character, StatusTree> getDicForward(){
		return this.seqFreqDic;
	}
	
	public Map<Character, StatusTree> getDicReverse(){
		return this.seqFreqRevDic;
	}
	
	public void out2Console(){
		String str = "";
		for(Entry<Character,StatusTree> en:seqFreqDic.entrySet()){
			this.dd(str, en.getValue().rootNode());
		}
	}
	
	private void dd(String str,TreeNode treeNode){
		if(treeNode.isEndpoint()){
			System.out.println(str+treeNode.getKey()+" "+treeNode.toString());
		}
		if(!treeNode.isLeaf()){
			for(Entry<Character,TreeNode> en:treeNode.subNodes().entrySet()){
				this.dd( str+treeNode.getKey(), en.getValue());
			}
		}
	}
	
	public int getMaxSeqLengthAllowed(){
		return this.maxSeqLengthAllowed;
	}

}
